import unittest
from alg import MinStack
from gen import CommandGenerator

class TestMinStack(unittest.TestCase):
    def test_example_case(self):
        stack = MinStack()
        results = []
        
        results.append(stack.push(-2))
        results.append(stack.push(0))
        results.append(stack.push(-3))
        results.append(stack.getMin())  # -3
        results.append(stack.pop())
        results.append(stack.top())     # 0
        results.append(stack.getMin())  # -2
        
        self.assertEqual(results, [None, None, None, -3, None, 0, -2])
    
    def test_empty_stack(self):
        stack = MinStack()
        self.assertEqual(stack.top(), None)
        self.assertEqual(stack.getMin(), None)
    
    def test_single_element(self):
        stack = MinStack()
        stack.push(5)
        self.assertEqual(stack.top(), 5)
        self.assertEqual(stack.getMin(), 5)
        stack.pop()
        self.assertEqual(stack.top(), None)
        self.assertEqual(stack.getMin(), None)
    
    def test_multiple_pushes_pops(self):
        stack = MinStack()
        stack.push(3)
        stack.push(2)
        stack.push(5)
        stack.push(1)
        
        self.assertEqual(stack.getMin(), 1)
        stack.pop()
        self.assertEqual(stack.getMin(), 2)
        stack.pop()
        self.assertEqual(stack.getMin(), 2)
        stack.pop()
        self.assertEqual(stack.getMin(), 3)
    
    def test_duplicate_min_values(self):
        stack = MinStack()
        stack.push(2)
        stack.push(2)
        stack.push(1)
        stack.push(1)
        
        self.assertEqual(stack.getMin(), 1)
        stack.pop()
        self.assertEqual(stack.getMin(), 1)
        stack.pop()
        self.assertEqual(stack.getMin(), 2)
    
    def test_large_random_commands(self):
        generator = CommandGenerator(max_commands=1000)
        commands = generator.generate(1000)
        
        stack = MinStack()
        reference = []  # 使用普通列表作为参考
        
        for cmd in commands:
            if cmd[0] == "push":
                val = cmd[1]
                stack.push(val)
                reference.append(val)
            elif cmd[0] == "pop":
                if reference:
                    reference.pop()
                stack.pop()
            elif cmd[0] == "top":
                expected = reference[-1] if reference else None
                self.assertEqual(stack.top(), expected)
            elif cmd[0] == "getMin":
                expected = min(reference) if reference else None
                self.assertEqual(stack.getMin(), expected)

if __name__ == '__main__':
    unittest.main()    